using System;
using System.IO;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

namespace ExcelTemplateEngine.OpenXML
{
    /// <summary>
    /// 基于OpenXML SDK的工作簿操作实现
    /// </summary>
    public class OpenXMLWorkbookOperations : IWorkbookOperations
    {
        /// <summary>
        /// 打开Excel文件
        /// </summary>
        /// <param name="filePath">Excel文件路径</param>
        /// <returns>工作簿对象</returns>
        public IWorkbook OpenWorkbook(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
                throw new ArgumentException("文件路径不能为空", nameof(filePath));
                
            if (!File.Exists(filePath))
                throw new FileNotFoundException($"文件不存在: {filePath}");
                
            var document = SpreadsheetDocument.Open(filePath, true);
            return new OpenXMLWorkbook(document);
        }
        
        /// <summary>
        /// 从流打开Excel文件
        /// </summary>
        /// <param name="stream">Excel文件流</param>
        /// <returns>工作簿对象</returns>
        public IWorkbook OpenWorkbook(Stream stream)
        {
            if (stream == null)
                throw new ArgumentNullException(nameof(stream));
                
            var document = SpreadsheetDocument.Open(stream, true);
            return new OpenXMLWorkbook(document);
        }
        
        /// <summary>
        /// 创建新的工作簿
        /// </summary>
        /// <returns>新的工作簿对象</returns>
        public IWorkbook CreateWorkbook()
        {
            var stream = new MemoryStream();
            var document = SpreadsheetDocument.Create(stream, SpreadsheetDocumentType.Workbook);
            
            // 创建必要的部件
            var workbookPart = document.AddWorkbookPart();
            workbookPart.Workbook = new Workbook();
            
            // 创建工作表集合
            var sheets = workbookPart.Workbook.AppendChild(new Sheets());
            
            // 创建共享字符串表
            var sharedStringPart = workbookPart.AddNewPart<SharedStringTablePart>();
            sharedStringPart.SharedStringTable = new SharedStringTable();
            
            // 创建样式表
            var stylesPart = workbookPart.AddNewPart<WorkbookStylesPart>();
            stylesPart.Stylesheet = CreateDefaultStylesheet();
            stylesPart.Stylesheet.Save();
            
            return new OpenXMLWorkbook(document);
        }
        
        /// <summary>
        /// 保存工作簿到文件
        /// </summary>
        /// <param name="workbook">工作簿对象</param>
        /// <param name="filePath">保存路径</param>
        public void SaveWorkbook(IWorkbook workbook, string filePath)
        {
            if (workbook == null)
                throw new ArgumentNullException(nameof(workbook));
            if (string.IsNullOrEmpty(filePath))
                throw new ArgumentException("文件路径不能为空", nameof(filePath));
                
            var openXmlWorkbook = workbook as OpenXMLWorkbook;
            if (openXmlWorkbook == null)
                throw new ArgumentException("无效的工作簿类型", nameof(workbook));
                
            var document = openXmlWorkbook.Document;
            
            // 保存到指定路径
            using (var fileStream = new FileStream(filePath, FileMode.Create))
            {
                document.Clone(fileStream);
            }
        }
        
        /// <summary>
        /// 保存工作簿到流
        /// </summary>
        /// <param name="workbook">工作簿对象</param>
        /// <param name="stream">目标流</param>
        public void SaveWorkbook(IWorkbook workbook, Stream stream)
        {
            if (workbook == null)
                throw new ArgumentNullException(nameof(workbook));
            if (stream == null)
                throw new ArgumentNullException(nameof(stream));
                
            var openXmlWorkbook = workbook as OpenXMLWorkbook;
            if (openXmlWorkbook == null)
                throw new ArgumentException("无效的工作簿类型", nameof(workbook));
                
            var document = openXmlWorkbook.Document;
            document.Clone(stream);
        }
        
        /// <summary>
        /// 创建默认样式表
        /// </summary>
        /// <returns>默认样式表</returns>
        private Stylesheet CreateDefaultStylesheet()
        {
            var stylesheet = new Stylesheet();
            
            // 字体
            var fonts = new Fonts();
            fonts.Count = 1;
            fonts.Append(new Font(
                new FontSize() { Val = 11 },
                new FontName() { Val = "Calibri" },
                new FontFamilyNumbering() { Val = 2 },
                new FontScheme() { Val = FontSchemeValues.Minor }
            ));
            stylesheet.Append(fonts);
            
            // 填充
            var fills = new Fills();
            fills.Count = 2;
            fills.Append(new Fill(new PatternFill() { PatternType = PatternValues.None }));
            fills.Append(new Fill(new PatternFill() { PatternType = PatternValues.Gray125 }));
            stylesheet.Append(fills);
            
            // 边框
            var borders = new Borders();
            borders.Count = 1;
            borders.Append(new Border(
                new LeftBorder(),
                new RightBorder(),
                new TopBorder(),
                new BottomBorder(),
                new DiagonalBorder()
            ));
            stylesheet.Append(borders);
            
            // 单元格样式索引
            var cellStyleXfs = new CellStyleFormats();
            cellStyleXfs.Count = 1;
            cellStyleXfs.Append(new CellFormat() 
            { 
                NumberFormatId = 0, 
                FontId = 0, 
                FillId = 0, 
                BorderId = 0 
            });
            stylesheet.Append(cellStyleXfs);
            
            // 单元格格式
            var cellFormats = new CellFormats();
            cellFormats.Count = 1;
            cellFormats.Append(new CellFormat() 
            { 
                NumberFormatId = 0, 
                FontId = 0, 
                FillId = 0, 
                BorderId = 0, 
                FormatId = 0 
            });
            stylesheet.Append(cellFormats);
            
            // 单元格样式
            var cellStyles = new CellStyles();
            cellStyles.Count = 1;
            cellStyles.Append(new CellStyle() 
            { 
                Name = "Normal", 
                FormatId = 0, 
                BuiltinId = 0 
            });
            stylesheet.Append(cellStyles);
            
            return stylesheet;
        }
    }
}